/**
 * 
 */
package cn.edu.bjtu.alex.rewrite.components;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Map.Entry;

import com.google.common.collect.Maps;

import cn.edu.bjtu.alex.rewrite.Context;
import cn.edu.bjtu.alex.rewrite.interfaces.Term;
import cn.edu.bjtu.alex.rewrite.interfaces.TermFeatureable;

/**
 * @author alex
 *
 */
public abstract class BaseOutputingData extends BaseComponent{
	private Map<String, TermFeatureable> featuredTermsMap = null;
	/**
	 * @param ctx
	 */
	public BaseOutputingData(Context ctx) {
		super(ctx);
		// TODO Auto-generated constructor stub
	}


	/* (non-Javadoc)
	 * @see cn.edu.bjtu.alex.rewrite.components.BaseComponent#fitInternal()
	 */
	@Override
	final protected void fitInternal() {
		
		this.featuredTermsMap = ctx.featuredTermsMap();
		quantizeTermVectors();
		BufferedWriter writer;
		try {
			File file = new File(ctx.getOutputDir(), ctx.getOutputVectorFileName());
			//若文件不存在则新建~存在必须清空
			writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), ctx.getCharset()));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		Iterator<Entry<String, Map<String, Map<String, Term>>>> iter = ctx.termTableIterator();
		
		while(iter.hasNext()) {
			Entry<String, Map<String, Map<String, Term>>> labelledDocsEntry = iter.next();
			String label = labelledDocsEntry.getKey();
			Integer labelId = getLabelId(label);
			if(labelId != null) {
				Map<String, Map<String, Term>>  docs = labelledDocsEntry.getValue();
				Iterator<Entry<String, Map<String, Term>>> docsIter = docs.entrySet().iterator();
				while(docsIter.hasNext()) {
					StringBuffer line = new StringBuffer();
					line.append(labelId).append(" ");
					Entry<String, Map<String, Term>> docsEntry = docsIter.next();
					Map<String, Term> terms = docsEntry.getValue();
					
					//用优先队列按照wordid进行排序
					Queue<Entry<String, Term>> sortTerms = maptoSort(terms);
					//遍历优先队列
					while(true){
						Entry<String, Term> sortTerm = sortTerms.poll();
						if(sortTerm == null)break;
						String word = sortTerm.getKey();
						Integer wordId = getWordId(word);
						
						if(wordId != null) {
							Term term = sortTerm.getValue();
							line.append(wordId).append(":").append(term.getTfidf()).append(" ");
						}else{
							throw new RuntimeException("shouldn't null");
						}
						
					}
					
					/*for(Entry<String, Term> termEntry : terms.entrySet()) {
						String word = termEntry.getKey();
						Integer wordId = getWordId(word);
						if(wordId != null) {
							Term term = termEntry.getValue();
							line.append(wordId).append(":").append(term.getTfidf()).append(" ");
						}
					}*/
					try {
						String element = line.toString().trim();
						LOG.debug("Write line: " + element);
						writer.write(element);
						writer.newLine();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			} else {
				LOG.warn("Label ID can not be found: label=" + label + ", labelId=null");
			}
		}
		try {
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		LOG.info("Finished: outputVectorFile=" + ctx.getOutputVectorFileName());
		
	}
	//这是2个钩子函数
	protected abstract void quantizeTermVectors();
//	protected abstract void quantizeLabelMappingAndDicitionary();
	
	private Integer getWordId(String word) {
		TermFeatureable term = featuredTermsMap.get(word);
		return term == null ? null : term.getId();
	}

	private Integer getLabelId(String label) {
		return ctx.getlabelId(label);
	}
	
	private Queue<Entry<String, Term>> maptoSort(Map<String, Term> terms){
		Queue<Entry<String, Term>> priorityQueue = new PriorityQueue<>(idComparator);
		for(Entry<String, Term> termEntry : terms.entrySet()) {
			String word = termEntry.getKey();
			Integer wordId = getWordId(word);
			if(wordId != null) {
				priorityQueue.add(termEntry);
			}
		}
		return priorityQueue;
	}
	
	//匿名Comparator实现
    public Comparator<Entry<String, Term>> idComparator = new Comparator<Entry<String, Term>>(){
        public int compare(Entry<String, Term> c1, Entry<String, Term> c2) {
            return (int) (getWordId(c1.getKey()) - getWordId(c2.getKey()));
        }
    };
}
